
#include "HttpServer.hpp"
#include <boost/asio/ip/v6_only.hpp>
// Report a failure
static void fail(boost::beast::error_code ec, char const *what)
{
    std::cerr << what << ": " << ec.message() << "\n";
}

HttpServer::HttpServer(std::int32_t port, std::string &doc_root, std::size_t thread_pool_size)
    : work_guard(boost::asio::make_work_guard(*this)),
      thread_pool_size(thread_pool_size),
      thread_pool(thread_pool_size),
      doc_root(doc_root),
      acceptor(boost::asio::make_strand(*this))
{
    boost::beast::error_code ec;

    // Open the acceptor

    auto endpoint = boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), port);
    acceptor.open(endpoint.protocol(), ec);
    acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), ec);
    acceptor.set_option(boost::asio::ip::v6_only(false), ec);
    if (ec)
    {
        fail(ec, "open");
        return;
    }

    // Allow address reuse
    acceptor.set_option(boost::asio::socket_base::reuse_address(true), ec);
    if (ec)
    {
        fail(ec, "set_option");
        return;
    }

    // Bind to the server address
    acceptor.bind(endpoint, ec);
    if (ec)
    {
        fail(ec, "bind");
        return;
    }

    // Start listening for connections
    acceptor.listen(
        boost::asio::socket_base::max_listen_connections, ec);
    if (ec)
    {
        fail(ec, "listen");
        return;
    }

    for (size_t i = 0; i < thread_pool_size; i++)
    {
        thread_pool.emplace_back(
            [this]
            { run(); });
    }

    do_accept();
}

void HttpServer::join()
{
    for (auto &thread : thread_pool)
    {
        if (thread.joinable())
        {
            thread.join();
        }
    }
}

HttpServer::~HttpServer()
{
    join();
}

void HttpServer::get(std::string target, RequestHandler handler)
{
    get_handlers[target] = handler;
}
void HttpServer::post(std::string target, RequestHandler handler)
{
    post_handlers[target] = handler;
}

HttpServer::RequestHandler &HttpServer::get(std::string target)
{
    return get_handlers[target];
}
HttpServer::RequestHandler &HttpServer::post(std::string target)
{
    return post_handlers[target];
}

void HttpServer::do_accept()
{
    acceptor.async_accept(
        [this](boost::system::error_code ec, boost::asio::ip::tcp::socket socket)
        {
            if (!ec)
            {
                // 启动一个新的会话来处理客户端连接
                boost::shared_ptr<HttpSession> new_session(new HttpSession(std::move(socket), doc_root, get_handlers, post_handlers));
                new_session->start();
            }

            // 继续监听新连接
            do_accept();
        });
}
